package com.sl.sdn.repository.impl;

import cn.hutool.core.util.StrUtil;
import com.sl.sdn.dto.TransportLineNodeDTO;
import com.sl.sdn.entity.node.AgencyEntity;
import com.sl.sdn.repository.TransportLineRepository;
import com.sl.sdn.util.TransportLineUtil;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
public class TransportLineRepositoryImpl implements TransportLineRepository {

    @Resource
    private Neo4jClient neo4jClient;

    @Override
    public TransportLineNodeDTO findShortestPath(AgencyEntity start, AgencyEntity end) {
        //AGENCY
        String nodeTag = AgencyEntity.class.getAnnotation(Node.class).value()[0];
        //定义语句
        String cypherQuery = StrUtil.format("MATCH path = shortestPath((n:{}) -[*..10]->(m:{}))\n" +
                "WHERE n.bid = $startId AND m.bid = $endId \n" +
                "RETURN path", nodeTag, nodeTag);

        //执行语句
        return this.neo4jClient.query(cypherQuery)
                .bind(start.getBid()).to("startId") //设置占位参数
                .bind(end.getBid()).to("endId")
                .fetchAs(TransportLineNodeDTO.class) //指定返回结果的数据类型
                .mappedBy((typeSystem, record) -> TransportLineUtil.mappedRecord(record))
                .one()
                .orElse(null);
    }

    /**
     * 成本优先的路线查询
     *
     * @param start 开始网点
     * @param end   结束网点
     * @return
     */
    @Override
    public TransportLineNodeDTO findCheapestPath(AgencyEntity start, AgencyEntity end) {
        String agencyTag = AgencyEntity.class.getAnnotation(Node.class).value()[0];

        String cypherQuery = StrUtil.format("MATCH path = (start:{}) -[*..10]->(end:{})\n" +
                "WHERE start.bid=$startId AND end.bid = $endId\n" +
                "UNWIND relationships(path) AS r\n" +
                "WITH sum(r.cost) AS cost, path\n" +
                "RETURN path ORDER BY cost ASC, LENGTH(path) ASC LIMIT 1", agencyTag, agencyTag);

        return this.neo4jClient.query(cypherQuery)
                .bind(start.getBid()).to("startId")
                .bind(end.getBid()).to("endId")
                .fetchAs(TransportLineNodeDTO.class)
                .mappedBy((typeSystem, record) -> TransportLineUtil.mappedRecord(record))
                .one()
                .orElse(null);
    }
}
